package com.yswy.backstage.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yswy.backstage.service.*;
import com.yswy.common.enums.TfPlatformEnums;
import com.yswy.common.enums.TriggerNodeEnums;
import com.yswy.common.enums.XtPlatformEnums;
import com.yswy.common.enums.base.Type3Enum;
import com.yswy.common.enums.base.TypeEnum;
import com.yswy.common.utils.StringUtils;
import com.yswy.common.utils.redis.RedisConstants;
import com.yswy.common.utils.redis.RedisUtil;
import com.yswy.domain.common.BasePojo;
import com.yswy.domain.entity.PackageManage;
import com.yswy.domain.entity.tf.*;
import com.yswy.domain.entity.user.User;
import com.yswy.domain.framework.context.CurrentUserContext;
import com.yswy.domain.mapper.tf.TgDeductionMapper;
import com.yswy.domain.mapper.tf.TgEventMapper;
import com.yswy.domain.vo.dto.BaseFilter;
import com.yswy.domain.vo.gld.addOrUpate.TgDeductionAddOrUpdate;
import com.yswy.domain.vo.gld.addOrUpate.TgDeductionChildAddOrUpdate;
import com.yswy.domain.vo.gld.addOrUpate.TgEventAddOrUpdate;
import com.yswy.domain.vo.gld.addOrUpate.TgEventChildAddOrUpdate;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.yswy.backstage.utils.CrudUtils.selectCount;
import static com.yswy.common.constants.WarnMsgConstants.NULL_MSG;

@Slf4j
@Service
public class TgEventServiceImpl extends ServiceImpl<TgEventMapper, TgEvent>
        implements TgEventService {
    @Autowired
    private  SsoService ssoService;
    @Autowired
    private  TgEventChildService tgEventChildService;
    @Autowired
    private  RedisUtil redisUtil;
    @Autowired
    private  TgChannelService tgChannelService;

    @Override
    public Page<TgEvent> pageTgEvent(BaseFilter req) {
        Page<TgEvent> pageTgEvents = baseMapper.pageTgEvent(req
                ,ssoService.isAdminToUserId(CurrentUserContext.getCurrentUser())
                , new Page<>(req.getPageNum() , req.getPageSize()) );
        for (TgEvent tgEvent:pageTgEvents.getRecords()){
            TypeEnum tfPlatformEnumsEnum = TypeEnum.typeEnumOf(TfPlatformEnums.class , tgEvent.getTfPlatform());
            tgEvent.setTfPlatform(tfPlatformEnumsEnum.getMessage());
            for (TgEventChild tgEventChild:tgEvent.getTgEventChildrens()){
                TypeEnum triggerNodeEnumsEnum = TypeEnum.typeEnumOf(TriggerNodeEnums.class , tgEventChild.getTriggerNode());
                tgEventChild.setTriggerNode(triggerNodeEnumsEnum.getMessage());
            }
        }
        return pageTgEvents;
    }

    @Override
    public List<TgEvent> listTgEvent(Long tgEventId) {
        List<TgEvent> tgEvents = baseMapper.listTgEvent(
                ssoService.isAdminToUserId(CurrentUserContext.getCurrentUser())
                , tgEventId);
        for (TgEvent tgEvent:tgEvents){
            TypeEnum tfPlatformEnumsEnum = TypeEnum.typeEnumOf(TfPlatformEnums.class , tgEvent.getTfPlatform());
            tgEvent.setTfPlatform(tfPlatformEnumsEnum.getMessage());
            for (TgEventChild tgEventChild:tgEvent.getTgEventChildrens()){
                TypeEnum triggerNodeEnumsEnum = TypeEnum.typeEnumOf(TriggerNodeEnums.class , tgEventChild.getTriggerNode());
                tgEventChild.setTriggerNode(triggerNodeEnumsEnum.getMessage());
            }
        }
        return tgEvents;
    }

    @Override
    public TgEvent getTgEventByChannel(String channel) {
        String key = RedisConstants.tgEvent+channel ;
        TgEvent tgEvent = null ;
        if (redisUtil.hasKey(key)){
            tgEvent = (TgEvent)redisUtil.getObejct(key);
        }else {
            tgEvent = baseMapper.getTgEventByChannel(channel);
        }
        if (tgEvent!=null){
            redisUtil.setForObjectTimeCustom(key, tgEvent, 1, TimeUnit.DAYS);
            return tgEvent;
        }else {
            return null ;
        }
    }

    @Override
    public void clearTgEventCacheByTgEventId(Long tgEventId) {
        List<TgChannel> tgChannels =tgChannelService.list(new LambdaQueryWrapper<TgChannel>()
                .eq(TgChannel::getTgEventId , tgEventId));
        for (TgChannel t:tgChannels) {
            redisUtil.delete(RedisConstants.tgEvent+t.getChannel());
        }
    }

    @Override
    public void clearTgEventCacheByChannel(String channel) {
        redisUtil.delete(RedisConstants.tgEvent+channel);
    }


    @Override
    public Boolean isExist(String identifier) {
        Integer count = count(new LambdaQueryWrapper<TgEvent>()
                .eq(TgEvent::getIdentifier , identifier)
                .eq(BasePojo::getIsDel , 0));
        if (count>0){
            return true ;
        }
        return false;
    }

    @Override
    @Transactional
    public void addOrUpadteTgEvent(TgEventAddOrUpdate res) {
        User user = CurrentUserContext.getCurrentUser();
        Boolean isExist =  isExist(res.getIdentifier());
        TgEvent tgEvent = null ;
        if (res.getId() != null){
            //更新数据
            tgEvent = getById(res.getId());
            TypeEnum tfPlatformEnumsEnum = TypeEnum.messageOf(TfPlatformEnums.class , res.getTfPlatform());
            res.setTfPlatform(tfPlatformEnumsEnum.toString());

            Assert.state(null != tgEvent && null != tgEvent.getId(), NULL_MSG);
            BeanUtil.copyProperties(res, tgEvent);
            BasePojo.setBase(user.getId().longValue(), false, tgEvent);
            updateById(tgEvent);

        }else {
            if (isExist){
                throw new IllegalStateException("编号已存在");
            }
            tgEvent = new TgEvent(res , user);
            save(tgEvent);
        }

        List<TgEventChild> tgEventChildrens = new ArrayList<>();
        if (res.getTgEventChildAddOrUpdates() != null){
            for (TgEventChildAddOrUpdate child:
                    res.getTgEventChildAddOrUpdates()) {
                if (child.getEventId() == null
                        || StringUtils.isEmpty(child.getTriggerNode())
                        || child.getSortId() == null){
                    throw new IllegalStateException("事件配置错误");
                }
                tgEventChildrens.add(new TgEventChild(child , tgEvent.getId()));
            }
        }
        if (tgEventChildrens.size()>0){
            tgEventChildService.remove(new LambdaQueryWrapper<TgEventChild>()
                    .eq(TgEventChild::getTgEventId , tgEvent.getId()));
            tgEventChildService.saveBatch(tgEventChildrens);
        }

        //清理扣量配置缓存
        clearTgEventCacheByTgEventId(tgEvent.getId());
    }

    @Override
    public void delTgEvent(Long tgEventId) {
        User user = CurrentUserContext.getCurrentUser();
        Integer count = selectCount(baseMapper, s -> s.eq(BasePojo::getId, tgEventId));
        Assert.state(null != count && 0 < count, "未找到指定信息，请刷新重试");
        TgEvent bo = new TgEvent();
        bo.setId(tgEventId);
        bo.setIsDel(1);
        BasePojo.setBase(user.getId().longValue(), false, bo);
        updateById(bo);
    }


}
